// Package config 负责应用配置的加载和管理
// 提供从JSON文件读取配置信息的功能，包括服务配置、豆包API配置等
package config

import (
	"encoding/json"
	"fmt"
	"os"
	"time"
)

// Duration 自定义时间间隔类型，支持JSON解析
type Duration time.Duration

// UnmarshalJSON 实现JSON反序列化
func (d *Duration) UnmarshalJSON(data []byte) error {
	var v interface{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	switch value := v.(type) {
	case float64:
		// 数字形式，默认为秒
		*d = Duration(time.Duration(value) * time.Second)
		return nil
	case string:
		// 字符串形式，解析duration
		duration, err := time.ParseDuration(value)
		if err != nil {
			return err
		}
		*d = Duration(duration)
		return nil
	default:
		return fmt.Errorf("invalid duration format")
	}
}

// MarshalJSON 实现JSON序列化
func (d Duration) MarshalJSON() ([]byte, error) {
	return json.Marshal(time.Duration(d).String())
}

// String 返回字符串表示
func (d Duration) String() string {
	return time.Duration(d).String()
}

// ToDuration 转换为标准time.Duration
func (d Duration) ToDuration() time.Duration {
	return time.Duration(d)
}

// Config 应用主配置结构体
// 包含服务运行所需的所有配置信息
type Config struct {
	Server         ServerConfig      `json:"server"`          // 服务器配置
	ActiveModel    string            `json:"active_model"`    // 当前激活的模型（"doubao"、"ollama"或"lmstudio"）
	NetAccess      string            `json:"net_access"`      // 网络访问模式
	AllowedDomains []string          `json:"allowed_domains"` // 允许访问的域名列表
	Security       SecurityConfig    `json:"security"`        // 安全配置
	Ollama         OllamaConfig      `json:"ollama"`          // Ollama配置
	Doubao         DoubaoConfig      `json:"doubao"`          // 豆包API配置
	LMStudio       LMStudioConfig    `json:"lmstudio"`        // LM Studio配置
	Cache          CacheConfig       `json:"cache"`           // 缓存配置
	Concurrency    ConcurrencyConfig `json:"concurrency"`     // 并发控制配置
	Logging        LoggingConfig     `json:"logging"`         // 日志配置
}

// ServerConfig 服务器配置结构体
type ServerConfig struct {
	Port         string   `json:"port"`          // 服务端口
	Host         string   `json:"host"`          // 服务主机地址
	ReadTimeout  Duration `json:"read_timeout"`  // 读取超时时间
	WriteTimeout Duration `json:"write_timeout"` // 写入超时时间
	IdleTimeout  Duration `json:"idle_timeout"`  // 空闲超时时间
}

// SecurityConfig 安全配置结构体
type SecurityConfig struct {
	APIKeyRequired bool   `json:"api_key_required"` // 是否需要API密钥
	APIKey         string `json:"api_key"`          // API密钥
	TLSEnabled     bool   `json:"tls_enabled"`      // 是否启用TLS
	CertFile       string `json:"cert_file"`        // 证书文件路径
	KeyFile        string `json:"key_file"`         // 私钥文件路径
}

// DoubaoConfig 豆包API配置结构体
type DoubaoConfig struct {
	APIURL     string   `json:"api_url"`     // API地址
	APIKey     string   `json:"api_key"`     // API密钥
	Model      string   `json:"model"`       // 使用的模型
	Timeout    Duration `json:"timeout"`     // 请求超时时间
	MaxRetries int      `json:"max_retries"` // 最大重试次数
}

// OllamaConfig Ollama API配置结构体
type OllamaConfig struct {
	APIURL     string   `json:"api_url"`     // API地址
	APIKey     string   `json:"api_key"`     // API密钥（可选）
	Model      string   `json:"model"`       // 使用的模型
	Timeout    Duration `json:"timeout"`     // 请求超时时间
	MaxRetries int      `json:"max_retries"` // 最大重试次数
}

// LMStudioConfig LM Studio API配置结构体
type LMStudioConfig struct {
	APIURL     string   `json:"api_url"`     // API地址
	APIKey     string   `json:"api_key"`     // API密钥（可选）
	Model      string   `json:"model"`       // 使用的模型
	Timeout    Duration `json:"timeout"`     // 请求超时时间
	MaxRetries int      `json:"max_retries"` // 最大重试次数
}

// CacheConfig 缓存配置结构体
type CacheConfig struct {
	Enabled bool     `json:"enabled"` // 是否启用缓存
	TTL     Duration `json:"ttl"`     // 缓存存活时间
}

// ConcurrencyConfig 并发控制配置结构体
type ConcurrencyConfig struct {
	MaxWorkers int `json:"max_workers"` // 最大工作协程数
	QueueSize  int `json:"queue_size"`  // 队列大小
}

// LoggingConfig 日志配置结构体
type LoggingConfig struct {
	Level  string `json:"level"`  // 日志级别
	Format string `json:"format"` // 日志格式
}

// RuleCondition 规则条件结构体
type RuleCondition struct {
	Content string `json:"content"` // 检查内容
	Value   bool   `json:"value"`   // 是否违规
}

// Rule 检查规则结构体
// 增加Activate字段，支持新格式
type Rule struct {
	RulesName  string          `json:"rules-name"` // 规则名称
	Activate   bool            `json:"activate"`   // 是否激活
	Conditions []RuleCondition `json:"conditions"` // 检查条件列表
}

// Rules 规则集合，改为数组
type Rules []Rule

// LoadConfig 从指定路径加载配置文件
// 返回解析后的配置对象和可能的错误
func LoadConfig(configPath string) (*Config, error) {
	// 读取配置文件
	data, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %w", err)
	}

	var config Config
	// 解析JSON配置
	if err := json.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("failed to parse config file: %w", err)
	}

	// 验证配置的有效性
	if err := validateConfig(&config); err != nil {
		return nil, fmt.Errorf("invalid config: %w", err)
	}

	return &config, nil
}

// LoadRules 从指定路径加载规则文件
// 返回解析后的规则集合和可能的错误
func LoadRules(rulesPath string) (Rules, error) {
	// 读取规则文件
	data, err := os.ReadFile(rulesPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read rules file: %w", err)
	}

	var wrapper struct {
		Rules Rules `json:"rules"`
	}
	// 解析JSON规则
	if err := json.Unmarshal(data, &wrapper); err != nil {
		return nil, fmt.Errorf("failed to parse rules file: %w", err)
	}

	return wrapper.Rules, nil
}

// validateConfig 验证配置的有效性
// 检查必要字段是否存在，配置值是否合理
func validateConfig(config *Config) error {
	if config.Server.Port == "" {
		return fmt.Errorf("server port is required")
	}

	if config.Doubao.APIURL == "" {
		return fmt.Errorf("doubao API URL is required")
	}

	if config.Doubao.APIKey == "" {
		return fmt.Errorf("doubao API key is required")
	}

	if config.Doubao.Model == "" {
		return fmt.Errorf("doubao model is required")
	}

	// 设置默认超时时间
	if config.Server.ReadTimeout == 0 {
		config.Server.ReadTimeout = Duration(30 * time.Second)
	}
	if config.Server.WriteTimeout == 0 {
		config.Server.WriteTimeout = Duration(30 * time.Second)
	}
	if config.Server.IdleTimeout == 0 {
		config.Server.IdleTimeout = Duration(120 * time.Second)
	}
	if config.Doubao.Timeout == 0 {
		config.Doubao.Timeout = Duration(30 * time.Second)
	}
	if config.Cache.TTL == 0 {
		config.Cache.TTL = Duration(3600 * time.Second)
	}

	return nil
}
